/*=============================================================

PROGRAMMING TECHNIQUES FOR SUPERCOMPUTERS

Assignment Number 3

Task 1 - Strided vector triad

=============================================================*/

#include <stdio.h>
#include "timing.hh"
#include <iostream>
#include <math.h>
#include <fstream>
#include <iostream>

double timeStamp()
{ 
  struct timeval tp;
  gettimeofday(&tp, NULL); 
  return((double)(tp.tv_sec + tp.tv_usec/1000000.0)); 
}

int main(int argc, char *argv[]) 
{
	double wcTimeStart,wcTimeEnd,cpuTimeStart,cpuTimeEnd,wcTime, cpTime;	
	
	std::ofstream fileouta("assignment3_1.dat");
	fileouta << "# N\t MFLOP/sec" << std::endl;
   double *a;
   double *b;
   double *c;
   double *d;
   double runtime;
   int M;
   int N = 1e7;
   int repeat;
   long noFlops;
   double mFlops;
	for (int k = 0; k<4; ++k)
	{
	
	   M = pow(2,k);
	   a = new double[N];
		b = new double[N];
		c = new double[N];
		d = new double[N];
		
		for (int i = 0; i<N; ++i)
		{	
			b[i] = i*2.0;
			c[i] = i*3.0;
			d[i] = i*1.0;
		}
	
		// Task 3.1: Strided Vector Triad a[i] = b[i] + c[i]*d[i]	
		repeat =1;
		runtime =0.;
		for (; runtime <0.1; repeat*=2)
		{	
		   
			wcTimeStart = timeStamp();
			for (int r=0; r<repeat; ++r)
			{
				for (int i = 0; i<N; i+=M)
				{
					a[i] = b[i] + c[i]*d[i];
				}
				if (a[N-1] <0.) std::cout << "Dummy Loop Encountered"<< std::endl;
			}
				wcTimeEnd = timeStamp();	
				runtime=wcTimeEnd-wcTimeStart;				
		}
		repeat/=2;
		noFlops = 2*N/M*repeat;
		mFlops = noFlops/(runtime*1000000);
		fileouta << M <<"\t" << mFlops << std::endl;
		std::cout << "M: " << M << ", perf: " << mFlops << " MFlop/s" << std::endl;
		
		delete [] a;
		delete [] b;
		delete [] c;
		delete [] d;	
	}
	return 0;
}
